#pragma once

namespace IcyCrystal {
	class Type;

	enum TokenType {
		TOKEN_NONE, 
		TOKEN_KEYWORD, TOKEN_EQUALS, TOKEN_SEMICOLON, TOKEN_EOF,

		TOKEN_LSQUARE, TOKEN_RSQUARE, TOKEN_LCURLY, TOKEN_RCURLY,
		TOKEN_LPARA, TOKEN_RPARA,

		TOKEN_COMMA,

		TOKEN_FLOAT, TOKEN_INT,

		TOKEN_STRING,

		TOKEN_PLUS, TOKEN_MINUS, TOKEN_MULT, TOKEN_DIV,

		TOKEN_CONV_INT_TO_FLOAT, TOKEN_CONV_LITERAL,

		TOKEN_IDENT_INT, TOKEN_IDENT_FLOAT, TOKEN_IDENT_CHAR,
		TOKEN_RETURN
	};

	struct Token {
	public:


		// The lexical type of the token.
		TokenType tokenType;

		// The semantical type of the token.
		Type* innerType;
		union _value {
			int intValue;
			string* stringValue;
			float floatValue;
		} value;


		void clear() {
			if( tokenType == TOKEN_KEYWORD )
				delete value.stringValue;

			tokenType = TOKEN_NONE;
			innerType = NULL;
			value.intValue = 0;
		}

		const char* tokenTypeToString(){
			switch(tokenType){
			case TOKEN_KEYWORD:
				return "TOKEN_KEYWORD";
				break;
			case TOKEN_EQUALS:
				return "TOKEN_EQUALS";
				break;
			case TOKEN_SEMICOLON:
				return "TOKEN_SEMICOLON";
				break;
			case TOKEN_EOF:
				return "TOKEN_EOF";
				break;
			case TOKEN_FLOAT:
				return "TOKEN_FLOAT";
				break;
			case TOKEN_INT:
				return "TOKEN_INT";
				break;
			case TOKEN_IDENT_INT:
				return "TOKEN_IDENT_INT";
				break;
			case TOKEN_PLUS:
				return "TOKEN_PLUS";
				break;
			case TOKEN_MINUS:
				return "TOKEN_MINUS";
				break;
			case TOKEN_MULT:
				return "TOKEN_MULT";
				break;
			case TOKEN_DIV:
				return "TOKEN_DIV";
				break;
			case TOKEN_LCURLY:
				return "TOKEN_LCURLY";
				break;
			case TOKEN_RCURLY:
				return "TOKEN_RCURLY";
				break;
			default:
				return "TOKEN_UNIDENTIFIED";
				break;
			}
		}
	};
}